package com.jindy.module.engineeringcost.service.impl;

import com.jindy.common.constant.Constants;
import com.jindy.common.constant.HttpStatus;
import com.jindy.common.core.domain.AjaxResult;
import com.jindy.common.core.domain.model.LoginUser;
import com.jindy.common.exception.base.BaseException;
import com.jindy.common.utils.DateUtils;
import com.jindy.common.utils.SecurityUtils;
import com.jindy.jpush.domain.UniPushDomain;
import com.jindy.jpush.utils.UniJpushUtils;
import com.jindy.module.approvalConfig.domain.ApprovalConfig;
import com.jindy.module.approvalConfig.mapper.ApprovalConfigMapper;
import com.jindy.module.approvalRecord.domain.ApprovalRecord;
import com.jindy.module.approvalRecord.mapper.ApprovalRecordMapper;
import com.jindy.module.engineeringcost.domain.EngineeringCost;
import com.jindy.module.engineeringcost.domain.EngineeringCostApprovalResult;
import com.jindy.module.engineeringcost.mapper.EngineeringCostMapper;
import com.jindy.module.engineeringcost.service.IEngineeringCostService;
import com.jindy.module.jpush.mapper.JpushMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 【工程部费用】Service业务层处理
 * 
 * @author jindy
 * @date 2023-01-31
 */
@Service
public class EngineeringCostServiceImpl implements IEngineeringCostService
{
    private static final Logger LOGGER = LoggerFactory.getLogger(EngineeringCostServiceImpl.class);
    @Resource
    private EngineeringCostMapper engineeringCostMapper;

    /**
     * 配置表
     */
    @Resource
    private ApprovalConfigMapper approvalConfigMapper;

    /**
     * 审批记录
     */
    @Resource
    private ApprovalRecordMapper approvalRecordMapper;

    /**
     * 通知设备表
     */
    @Resource
    private JpushMapper jpushMapper;

    /**
     * 查询【工程部费用】
     * 
     * @param id 【工程部费用】主键
     * @return 【工程部费用】
     */
    @Override
    public EngineeringCost selectEngineeringCostById(Long id)
    {
        return engineeringCostMapper.selectEngineeringCostById(id);
    }

    /**
     * 查询【工程部费用】列表
     * 
     * @param engineeringCost 【工程部费用】
     * @return 【工程部费用】
     */
    @Override
    public List<EngineeringCost> selectEngineeringCostList(EngineeringCost engineeringCost)
    {
        return engineeringCostMapper.selectEngineeringCostList(engineeringCost);
    }

    /**
     * 查询【工程部费用】列表 (含数据权限)
     *
     * @param engineeringCost 【工程部费用】
     * @return 【工程部费用】
     */
    @Override
    public List<EngineeringCostApprovalResult> selectEngineeringCostListPermission(EngineeringCost engineeringCost)
    {
        //获取当前登录人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (Objects.isNull(loginUser)){
            throw new BaseException("查询【工程部费用】列表-请先登录");
        }
        Long loginUserUserId = loginUser.getUserId();
        //江磊可见所有数据
        List<ApprovalConfig> approvalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("GCGL_ADMIN", "1"));
        if (CollectionUtils.isEmpty(approvalConfigList)){
            throw new BaseException("查询【工程部费用】列表-请检查配置：GCGL_ADMIN");
        }
        List<Long> userIds = approvalConfigList.stream().map(ApprovalConfig::getUserId).collect(Collectors.toList());
        if (userIds.contains(loginUserUserId)){
            loginUserUserId=null;
        }
        //数据权限：服务人员,对应的业务员,提交人可看对应的数据
        return engineeringCostMapper.selectEngineeringCostListPermission(engineeringCost,loginUserUserId);
    }

    /**
     * 新增【工程部费用】
     * 
     * @param engineeringCost 【工程部费用】
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertEngineeringCost(EngineeringCost engineeringCost)
    {
        // 获取当前人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            return AjaxResult.error(HttpStatus.UNAUTHORIZED,"请先登录");
        }
        if (null == engineeringCost.getId()){
            engineeringCost.setCreateTime(DateUtils.getNowDate());
            engineeringCost.setCreateBy(loginUser.getUsername());
            engineeringCostMapper.insertEngineeringCost(engineeringCost);
        }else{
            engineeringCost.setCreateTime(DateUtils.getNowDate());
            engineeringCost.setCreateBy(loginUser.getUsername());
            engineeringCostMapper.updateEngineeringCost(engineeringCost);
            //删除审批记录
            approvalRecordMapper.deleteApprovalRecordBySerialNum(engineeringCost.getSerialNum());
        }
        // 新增审批记录
        List<Long> approvalPerson = addApprovalRecord(engineeringCost, loginUser);
        //发送通知下一审批人
        sendApproveMessage(approvalPerson);
        //通知业务员
        sendMessageToSalesman(engineeringCost);

        return AjaxResult.success();
    }

    /**
     * 发送通知
     * @param addJpushList
     */
    private void sendApproveMessage(List<Long> addJpushList) {
        try {
            List<String> addRegIds = jpushMapper.selectRegistrationIdsByUserIds(addJpushList);
            if (!CollectionUtils.isEmpty(addRegIds)){
                UniJpushUtils.sendApproveMessage(addRegIds);
            }
        } catch (Exception e) {
            LOGGER.error("工程部费用发送通知失败",e);
        }
    }

    /**
     * 通知业务员
     * @param engineeringCost
     */
    private void sendMessageToSalesman(EngineeringCost engineeringCost) {
        try {
            List<String> addRegIds = jpushMapper.selectRegistrationIdsByUserIds(Collections.singletonList(engineeringCost.getSalesman()));
            if (!CollectionUtils.isEmpty(addRegIds)) {
                UniPushDomain uniPushDomain = new UniPushDomain(addRegIds, "湿云", "有一条新的工程部管理单，请查看！");
                UniJpushUtils.doPost(uniPushDomain);
            }else {
                throw new BaseException("未找到业务员设备id");
            }
        } catch (Exception e) {
            LOGGER.error("工程部费用发送通知失败",e);
        }
    }
    /**
     * 发起人是内部人员 流程记录
     *
     * @param engineeringCost
     * @param loginUser
     */
    @Transactional(rollbackFor = Exception.class)
    public List<Long> addApprovalRecord(EngineeringCost engineeringCost, LoginUser loginUser) {

        int sequence = 1;
        //  发起人
        ApprovalRecord firstApprovalRecord = getApprovalRecord(engineeringCost, loginUser);
        firstApprovalRecord.setSequence(sequence);
        firstApprovalRecord.setApprovalStatus(Constants.COMPLETED);
        firstApprovalRecord.setTypeOperation(Constants.AGREE);
        firstApprovalRecord.setBusinessStatus(Constants.APPROVE);
        firstApprovalRecord.setApproverId(loginUser.getUserId());
        firstApprovalRecord.setApproverName(loginUser.getUsername());
        approvalRecordMapper.insertApprovalRecord(firstApprovalRecord);

        sequence++;
        //  服务人员
        ApprovalRecord fwPerson = getApprovalRecord(engineeringCost, loginUser);
        fwPerson.setApprovalStatus(Constants.APPROVE);
        fwPerson.setSequence(sequence);
        fwPerson.setApproverId(engineeringCost.getUserId());
        fwPerson.setApproverName(engineeringCost.getUserName());
        approvalRecordMapper.insertApprovalRecord(fwPerson);

        sequence++;
        //  江磊审批
        List<ApprovalConfig> approvalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("GCGL_SP_LEADER", "1"));
        if (CollectionUtils.isEmpty(approvalConfigList)) {
            throw new RuntimeException("请检查审批配置信息：GCGL_SP_LEADER");
        }
        addApprovalConfig(sequence, approvalConfigList,engineeringCost, loginUser);

        sequence++;
        //  业务员
        ApprovalRecord ywPerson = getApprovalRecord(engineeringCost, loginUser);
        ywPerson.setApprovalStatus(Constants.NOT_APPROVED);
        ywPerson.setApproverId(engineeringCost.getSalesman());
        ywPerson.setSequence(sequence);
        ywPerson.setApproverName(engineeringCost.getSalesmanName());
        approvalRecordMapper.insertApprovalRecord(ywPerson);

        return Collections.singletonList(fwPerson.getApproverId());
    }

    /**
     * 新增第二，第三审批记录信息
     *
     * @param sequence
     * @param approvalConfigList
     */
    @Transactional(rollbackFor = Exception.class)
    public void addApprovalConfig(int sequence, List<ApprovalConfig> approvalConfigList,EngineeringCost engineeringCost, LoginUser loginUser) {
        String status = Constants.NOT_APPROVED;
        if (sequence == 2) {
            status = Constants.APPROVE;
        }
        for (ApprovalConfig approvalConfig : approvalConfigList) {
            ApprovalRecord approvalRecord = getApprovalRecord(engineeringCost,loginUser);
            approvalRecord.setSequence(sequence);
            approvalRecord.setApprovalStatus(status);
            approvalRecord.setApproverId(approvalConfig.getUserId());
            approvalRecord.setApproverName(approvalConfig.getUsername());
            approvalRecordMapper.insertApprovalRecord(approvalRecord);
        }
    }

    /**
     * 获取审批记录对象
     *
     * @param engineeringCost
     * @param loginUser
     * @return
     */
    private ApprovalRecord getApprovalRecord(EngineeringCost engineeringCost, LoginUser loginUser) {
        ApprovalRecord approvalRecord = new ApprovalRecord();
        approvalRecord.setSerialNum(engineeringCost.getSerialNum());
        approvalRecord.setUserId(loginUser.getUserId());
        approvalRecord.setOrderId(engineeringCost.getId());
        approvalRecord.setUserName(loginUser.getUsername());
        approvalRecord.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        approvalRecord.setUpdateBy(loginUser.getUsername());
        approvalRecord.setCreateBy(loginUser.getUsername());
        approvalRecord.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
        return approvalRecord;
    }

    /**
     * 修改【工程部费用】
     * 
     * @param engineeringCost 【工程部费用】
     * @return 结果
     */
    @Override
    public int updateEngineeringCost(EngineeringCost engineeringCost)
    {
        engineeringCost.setUpdateTime(DateUtils.getNowDate());
        return engineeringCostMapper.updateEngineeringCost(engineeringCost);
    }

    /**
     * 批量删除【工程部费用】
     * 
     * @param ids 需要删除的【工程部费用】主键
     * @return 结果
     */
    @Override
    public int deleteEngineeringCostByIds(Long[] ids)
    {
        return engineeringCostMapper.deleteEngineeringCostByIds(ids);
    }

    /**
     * 删除【工程部费用】信息
     * 
     * @param id 【工程部费用】主键
     * @return 结果
     */
    @Override
    public int deleteEngineeringCostById(Long id)
    {
        return engineeringCostMapper.deleteEngineeringCostById(id);
    }
}
